package com.password.services;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.ehcache.CachePersistenceException;
import org.ehcache.PersistentUserManagedCache;

import com.password.entity.User;
import com.password.exception.ManagerException;
import com.password.util.CacheUtil;
import com.password.util.DesUtil;
import com.password.util.PasswordUtil;
import com.password.util.ManagerExceptionUtil;
import com.password.util.ManagerExceptionUtil.Status;
import com.password.util.RSAEncryptUtil;
import com.password.util.SystemConfig;

/**
 * 用户服务
 * 
 * @author yzh
 * @date 2020年5月26日
 *
 */
public class UserService {

	private UserService() {
	}

	private Object lock = new Object();

	private static class UserServicesBuilder {
		private static UserService userServices = new UserService();
	}

	public static UserService getUserServices() {
		return UserServicesBuilder.userServices;
	}

	/**
	 * 用户添加
	 * 
	 * @author yzh
	 * @date 2020年5月27日
	 * 
	 * @param userNane
	 * @param password
	 * @return
	 * @throws CachePersistenceException
	 */
	public User addUser(String userNane, String password) {
		if (StringUtils.isEmpty(userNane)) {
			throw new ManagerException(ManagerExceptionUtil.userNameEmptyStatus);
		}
		if (StringUtils.isEmpty(password)) {
			throw new ManagerException(ManagerExceptionUtil.passwordEmptyStatus);
		}
		userNane = userNane.trim();
		password = password.trim();
		synchronized (lock) {
			try (PersistentUserManagedCache<String, User> userCache = CacheUtil.getUserCache();) {
				User emptyUser = new User();
				User putIfAbsent = userCache.putIfAbsent(userNane, emptyUser);
				if (putIfAbsent != null)
					throw new ManagerException(ManagerExceptionUtil.userExistsStatus);
				emptyUser.setUserName(userNane);
				// 给密码进行MD5加密
				emptyUser.setPassword(PasswordUtil.getEncrptPassword(password));
				// 设置DES的固定key,主要用于加密私钥
				emptyUser.setFixedDexKey(DesUtil.randGenerateDESKey());
				// 生成RSA秘钥对，公钥保存在用户信息中用于加密，私钥由用户保存，默认方法上下文目录下
				Map<Integer, String> genKeyPair = RSAEncryptUtil.genKeyPair();
				emptyUser.setRsaKey(genKeyPair.get(0));
				// 将私钥文件保存到指定目录下
				File file = new File(SystemConfig.getContextPath(), SystemConfig.getUserPrivateKeyFileName(userNane));
				if (file.exists()) {
					file.delete();
				}
				if (!file.exists()) {
					file.createNewFile();
					String sys = System.getProperty("os.name");
					if (StringUtils.containsIgnoreCase(sys, "windows")) {
						Files.setAttribute(file.toPath(), "dos:hidden", true);
					}
				}
				try (OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file,true));) {
					write.write(DesUtil.encrypt(genKeyPair.get(1), emptyUser.getFixedDexKey(), "UTF-8"));
				}
				userCache.put(userNane, emptyUser);
				return userCache.get(userNane);
			} catch (Exception e) {
				throw new ManagerException(Status.BuildExceptionStatus("500", e.getMessage()));
			}
		}
	}

	public boolean isExistUser(String userName) {
		if (StringUtils.isBlank(userName)) {
			return false;
		}
		try (PersistentUserManagedCache<String, User> userCache = CacheUtil.getUserCache();) {
			return userCache.containsKey(StringUtils.trim(userName));
		}
	}

	public PersistentUserManagedCache<String, User> getUserCache() {
		return CacheUtil.getUserCache();
	}

	/**
	 * 校验用户名和密码
	 * 
	 * @author yzh
	 * @date 2020年5月27日
	 * 
	 * @param user
	 * @param password
	 * @return
	 */
	public void verifyPassword(String user, String password) {
		try (PersistentUserManagedCache<String, User> userCache = CacheUtil.getUserCache();) {
			User userM = userCache.get(user);
			if (userM == null) {
				throw new ManagerException(ManagerExceptionUtil.userOrPasswordErrorStatus);
			}
			boolean verifyMD5 = PasswordUtil.verifyPassword(userM.getPassword(), password);
			if (!verifyMD5) {
				throw new ManagerException(ManagerExceptionUtil.userOrPasswordErrorStatus);
			}

		}
	}

	/**
	 * 更新密码
	 * 
	 * @author yzh
	 * @date 2020年5月27日
	 * @param user
	 * @param newPassword
	 */
	public void updatePassword(String user, String oldPassword, String newPassword) {
		synchronized (lock) {
			verifyPassword(user, oldPassword);
			try (PersistentUserManagedCache<String, User> userCache = CacheUtil.getUserCache();) {
				User userM = userCache.get(user);
				userM.setPassword(PasswordUtil.getEncrptPassword(newPassword));
				userCache.put(user, userM);
			}
		}
	}

	/**
	 * 获取指定用户，如果用户名和密码校验不通过则会抛出异常
	 * 
	 * @author yzh
	 * @date 2020年5月27日
	 * 
	 * @param user
	 * @param password
	 * @return
	 */
	public User getUser(String user, String password) {
		synchronized (lock) {
			verifyPassword(user, password);
			try (PersistentUserManagedCache<String, User> userCache = CacheUtil.getUserCache();) {
				return userCache.get(user);
			}
		}
	}

	public static void main(String[] args) {
		String property = System.getProperty("os.name");
		if (StringUtils.containsIgnoreCase("windows", property)) {
			System.out.println("windows系统");
		}
		System.out.println(property);
	}

}
